﻿using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Moonlite.ExtensionApi.GlobalInterfaces;

namespace Moonlite.Platform.Text.File
{
    public static class TemplateParser
    {
        public static string NamePattern = @"<%Name=""(?<value>[\w \t]*)""%>";
        public static string DescriptionPattern = @"<%Description=""(?<value>[\w\s,.-_'\*\!\@\""\#\$\%\&\/\(\)\=\?\+\{\[\]\}]*)""%>";
        public static string CategoryPattern = @"<%Category=""(?<value>[\w \t]*)""%>";
        public static string FileExtensionPattern = @"<%FileExtension=""(?<value>[\w \t]*)""%>";
        public static string TemplateCategoryPattern = @"<%TemplateCategory=""(?<value>[\w \t]*)""%>";
        public static ITemplate ParseTemplateHeader(string filename)
        {
            string fileContent = "";
            using (StreamReader reader = new StreamReader(filename))
            {
                fileContent = reader.ReadToEnd();
                reader.Close();
            }

            string name = "";
            string description = "";
            string category = "";
            string fileExtension = "";
            string templateCategory = "";
            Array.ForEach(fileContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.None), line =>
            {
                Match nameMatch = Regex.Match(line, NamePattern);
                Match descriptionMatch = Regex.Match(line, DescriptionPattern);
                Match categoryMatch = Regex.Match(line, CategoryPattern);
                Match fileExtensionMatch = Regex.Match(line, FileExtensionPattern);
                Match templateCategoryMatch = Regex.Match(line, TemplateCategoryPattern);
                if (nameMatch.Success == true)
                {
                    name = nameMatch.Groups["value"].Value;
                }
                else if (descriptionMatch.Success == true)
                {
                    description = descriptionMatch.Groups["value"].Value;
                }
                else if (categoryMatch.Success == true)
                {
                    category = categoryMatch.Groups["value"].Value;
                }
                else if (fileExtensionMatch.Success == true)
                {
                    fileExtension = fileExtensionMatch.Groups["value"].Value;
                }
                else if (templateCategoryMatch.Success == true)
                {
                    templateCategory = templateCategoryMatch.Groups["value"].Value;
                }
            });

            if (name == "" || (category == "" || (category.ToLower() != "jass" && category.ToLower() != "galaxy")))
            {
                return null;
            }

            return new Template { Name = name, Description = description, Category = category, FileName = filename, FileExtension = fileExtension, TemplateCategory = templateCategory };
        }

        public static TemplateCollection GetAllTemplates()
        {
            string directoryPath = Application.StartupPath + "\\Templates";
            TemplateCollection templates = new TemplateCollection();
            DirectoryInfo info = new DirectoryInfo(directoryPath);
            Array.ForEach(info.GetFiles("*.mtp"), fileInfo =>
            {
                ITemplate template = ParseTemplateHeader(fileInfo.FullName);
                if (template != null)
                {
                    templates.Add(template);
                }
            });

            return templates;
        }

        public static string Parse(ITemplate template)
        {
            string input = "";
            using (StreamReader reader = new StreamReader(template.FileName))
            {
                input = reader.ReadToEnd();
                reader.Close();
            }

            int projectNameIndex = -1;
            int fileNameIndex = -1;
            string excludedText = "";
            Array.ForEach(input.Split(new string[] { Environment.NewLine }, StringSplitOptions.None), line =>
            {
                if (line != "<%Name=\"" + template.Name + "\"%>" && line != "<%Description=\"" + template.Description + "\"%>" && line != "<%Category=\"" + template.Category + "\"%>" && line != "<%FileExtension=\"" + template.FileExtension + "\"%>" && line != "<%TemplateCategory=\"" + template.TemplateCategory + "\"%>")
                {
                    excludedText += line + Environment.NewLine;
                }
            });

            if (excludedText.Length > Environment.NewLine.Length)
            {
                input = excludedText.Substring(0, excludedText.Length - Environment.NewLine.Length);
                while (true)
                {
                    projectNameIndex = input.IndexOf("<%ProjectName%>");
                    fileNameIndex = input.IndexOf("<%FileName%>");
                    bool nonDefaultPropertiesExist = false;
                    foreach (string propertyName in AvailableProperties.Properties.Keys)
                    {
                        int propertyNameIndex = input.IndexOf(String.Format("<%{0}%>", propertyName));
                        if (propertyNameIndex > -1)
                        {
                            nonDefaultPropertiesExist = true;
                        }
                    }

                    bool shouldBreak = projectNameIndex == -1 && fileNameIndex == -1 && nonDefaultPropertiesExist == false;
                    if (shouldBreak == true)
                    {
                        break;
                    }

                    input = input.Replace("<%ProjectName%>", AvailableProperties.ProjectName);
                    input = input.Replace("<%FileName%>", AvailableProperties.FileName);
                    input = input.Replace("<%Package%>", AvailableProperties.Package);
                    foreach (string propertyName in AvailableProperties.Properties.Keys)
                    {
                        int propertyNameIndex = input.IndexOf(String.Format("<%{0}%>", propertyName));
                        if (propertyNameIndex > -1)
                        {
                            input = input.Replace(String.Format("<%{0}%>", propertyName), AvailableProperties.GetProperty(propertyName));
                        }
                    }
                }
            }
            else
            {
                input = excludedText;
            }

            return input;
        }
    }
}
